using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using System.Threading.Tasks;
using UnityEditor;
using UnityEngine;

namespace EGEngine
{
    public class UIModule : MonoBehaviour
    {
        public Transform UIRoot;
        [HideInInspector] public Camera UICamera;
        [HideInInspector] public Canvas UICanvas;
        public List<string> UILayers;
        public Dictionary<EUIPageType, RectTransform> TypeNodeDic;
        private Dictionary<Type, UIPage> TypePageDic;
        private ResourceLoader _resourceLoader;

        public void Init()
        {
            TypePageDic = new Dictionary<Type, UIPage>();
            TypeNodeDic = new Dictionary<EUIPageType, RectTransform>();
            UICamera = UIRoot.Find("UICamera").GetComponent<Camera>();
            UICanvas = UIRoot.GetComponent<Canvas>();
            for (int i = 0; i < UILayers.Count; i++)
            {
                var layerGo = new GameObject(UILayers[i]);
                layerGo.transform.SetParent(UIRoot);
                var rect = layerGo.GetComponent<RectTransform>();
                rect.localPosition = Vector3.zero;
                rect.localScale = Vector3.one;
                rect.SetSiblingIndex(i);
                TypeNodeDic[(EUIPageType)i] = rect;
            }
        }

        public void ShowPageSync<T>(params object[] data) where T : UIPage, new()
        {
            T t = new T();
            var type = t.GetType();
            if (!TypePageDic.ContainsKey(type))
            {
                var attribute = t.GetType().GetCustomAttribute<UIPageAttribute>();
                t.PrefabLocation = attribute.PrefabLocation;
                t.PageType = attribute.PageType;
                t.gameObject = _resourceLoader.LoadSync<GameObject>(t.PrefabLocation);
                t.transform = t.gameObject.transform;
                t.rectTransform = t.gameObject.GetComponent<RectTransform>();
                t.transform.SetParent(TypeNodeDic[t.PageType]);
                t.transform.localPosition = Vector3.zero;
                t.transform.localScale = Vector3.one;
                t.resourceLoader = ResourceModule.CreateResourceLoader();
                t.Awake();
            }

            t.gameObject.SetActive(true);
            t.transform.SetAsLastSibling();
            t.OnShowSync(data);
        }

        public void HidePageSync<T>() where T : UIPage, new()
        {
            T t = new T();
            var type = t.GetType();
            if (!TypePageDic.ContainsKey(type))
            {
                t.gameObject.SetActive(false);
                t.OnHideSync();
            }
        }

        public void ClosePageSync<T>() where T : UIPage, new()
        {
            T t = new T();
            var type = t.GetType();
            if (!TypePageDic.ContainsKey(type))
            {
                t.gameObject.SetActive(false);
                t.OnHideSync();
                t.OnCloseSync();
                Destroy(t.gameObject);
                TypePageDic.Remove(type);
                t.resourceLoader.Release();
                _resourceLoader.Release();
            }
        }

        public async Task ShowPageAsync<T>(params object[] data) where T : UIPage, new()
        {
            T t = new T();
            var type = t.GetType();
            if (!TypePageDic.ContainsKey(type))
            {
                var attribute = t.GetType().GetCustomAttribute<UIPageAttribute>();
                t.PrefabLocation = attribute.PrefabLocation;
                t.PageType = attribute.PageType;
                t.gameObject = await _resourceLoader.LoadAsync<GameObject>(t.PrefabLocation);
                t.transform = t.gameObject.transform;
                t.rectTransform = t.gameObject.GetComponent<RectTransform>();
                t.transform.SetParent(TypeNodeDic[t.PageType]);
                t.transform.localPosition = Vector3.zero;
                t.transform.localScale = Vector3.one;
                t.resourceLoader = ResourceModule.CreateResourceLoader();
                t.Awake();
            }

            t.gameObject.SetActive(true);
            t.transform.SetAsLastSibling();
            await t.OnShowAsync(data);
        }

        public async Task HidePageAsync<T>() where T : UIPage, new()
        {
            T t = new T();
            var type = t.GetType();
            if (!TypePageDic.ContainsKey(type))
            {
                t.gameObject.SetActive(false);
                await t.OnHideAsync();
            }
        }

        public async Task ClosePageAsync<T>() where T : UIPage, new()
        {
            T t = new T();
            var type = t.GetType();
            if (!TypePageDic.ContainsKey(type))
            {
                t.gameObject.SetActive(false);
                await t.OnHideAsync();
                await t.OnCloseAsync();
                Destroy(t.gameObject);
                TypePageDic.Remove(type);
                t.resourceLoader.Release();
                _resourceLoader.Release();
            }
        }

        public void RefreshPage<T>(params object[] data) where T : UIPage, new()
        {
            T t = new T();
            var type = t.GetType();
            if (!TypePageDic.ContainsKey(type))
            {
                t.OnRefresh(data);
            }
        }
    }
}